package com.letoo.sso.core.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
//import com.letoo.notification.rpc.client.SmsRPCService;
//import com.letoo.notification.rpc.entity.SmsTemplate;
import com.letoo.sso.common.domain.ContextConstants;
import com.letoo.sso.common.domain.Result;
import com.letoo.sso.common.domain.ResultCode;
import com.letoo.sso.common.exception.BusinessException;
import com.letoo.sso.common.utils.AESUtils;
import com.letoo.sso.common.utils.MathUtils;
import com.letoo.sso.common.utils.MyHttpclientUtils;
import com.letoo.sso.common.utils.RegexUtils;
import com.letoo.sso.core.service.AppBaseConfigService;
import com.letoo.sso.core.service.CaptchaService;
import com.letoo.sso.core.service.UserService;
import com.letoo.sso.dataaccess.dao.cahce.CaptchaCacheDAO;
import com.letoo.sso.dataaccess.dao.cahce.impl.CaptchaCacheDAOImpl;
import com.letoo.sso.dataaccess.internal.SendSmsRequest;

/**
 * 验证码服务接口实现
 * 
 * @author: dengjie
 */
@Service("captchaService")
public class CaptchaServiceImpl implements CaptchaService {

    /**
     * 日志
     */
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserService userService;

    @Autowired
    private CaptchaCacheDAO captchaCacheDAO;

    @Autowired
    private AppBaseConfigService appBaseConfigService;

    @Value("${biz.mainapp.url}")
    private String bizMainUrl;

    @Override
    public Result applyRegisterCaptcha(String mobile) {
        // 由于加密了，所以传入的手机号码都是密文肯定不是手机号码格式的，那么这里正则匹配一下，如果是手机格式那么直接返回不需要进行解密浪费性能。
        if (RegexUtils.Mobile(mobile)) {
            Result res = new Result(ResultCode.COMMON_FAILED, false);
            return res;
        }
        // 解密，前端加密了。
        // 用户注册的时候客户端传入的是加密后的明文密码，所以存入数据库需要进行解密并且MD5BASE64摘要。
        String mobileSecretKey = appBaseConfigService.getAppBaseConfig(ContextConstants.APP_ID,
                ContextConstants.CAPTCHA_SECRET_KEY);
        log.info("CaptchaServiceImpl applyRegisterCaptcha method.app send mobile is:" + mobile);
        log.info("CaptchaServiceImpl applyRegisterCaptcha method.mobileSecretKey is:" + mobileSecretKey);

        mobile = AESUtils.decrypt(mobile, mobileSecretKey);
        // 校验注册的时候手机号码是否已经注册过。如果已经注册了，那么就不能发验证码。保证一个手机号对应一个用户
        Result res = userService.mobileIsExisted(mobile);
        // false表示没有注册过
        if (res.isSuccess() == false) {
            // 生成验证码
            String captcha = captchaCacheDAO.getRegisterCaptcha(mobile);
            // 已经发送了验证码的，在缓存消失之前不能再生成。验证码设置了消失时间。即验证码有效期。
            // 获取有效期，当手机号在60s过后，是允许用户重新发送短信的，判定逻辑是获取key的TTL剩余有效时间来计算是否已经超过60s，而不是判断验证码缓存是否存储
            Long registerCaptchaTTL = captchaCacheDAO.getRegisterCaptchaTTL(mobile);
            Long expireTime = CaptchaCacheDAOImpl.CAPTCHA_EXPIRE_TIME;
            if (StringUtils.isBlank(captcha) || (expireTime - 60) > registerCaptchaTTL) {
                captcha = MathUtils.getRandowNumber(4);
                /** RPC调用消息系统发送短信，这里只做短信内容组装 **/
                Map<String, String> templateArgs = new HashMap<String, String>();
                templateArgs.put("code", captcha);
                templateArgs.put("product", "农商通APP");
                // 以后修改成springcloud内部接口调用
                SendSmsRequest sendSmsRequest = new SendSmsRequest();
                sendSmsRequest.setParamStrings(templateArgs);
                List<String> mobiles = new ArrayList<String>();
                mobiles.add(mobile);
                sendSmsRequest.setPhoneNumberArr(mobiles);
                sendSmsRequest.setTemplateCode("SMS_56085114");
                Map<String,String> headers = new HashMap<String,String>();
                headers.put("Accept", "application/vnd.dragon.app-v1.0+json");
                MyHttpclientUtils.doPostForJson(bizMainUrl.concat("/int/sms/send"), JSON.toJSONString(sendSmsRequest),
                        headers);
                // smsRPCService.sendToSingleUserDynaTemplate(mobile, SmsTemplate.REGISTER_CAPTCHA, templateArgs);
                /** RPC调用消息系统发送短信，这里只做短信内容组装 **/
                res.setSuccess(true);
                if (res.isSuccess()) {
                    // 短信发送成功，把验证码设置到缓存中.
                    captchaCacheDAO.setRegisterCaptcha(mobile, captcha);
                    res.setResultCode(ResultCode.COMMON_SUCCESS);
                    res.setSuccess(true);
                }
            } else {
                res.setResultCode(ResultCode.COMMON_FAILED);
                res.setSuccess(false);
            }
        } else {
            // 该手机号码已经注册，提示前端
            throw new BusinessException(ResultCode.SSO_REGISTER_MOBILE_IS_EXISTED,
                    "register mobile is exist,the mobile is：" + mobile);
        }
        return res;
    }

    @Override
    public Result applyPasswordCaptcha(String mobile) {
        // 由于加密了，所以传入的手机号码都是密文肯定不是手机号码格式的，那么这里正则匹配一下，如果是手机格式那么直接返回不需要进行解密浪费性能。
        if (RegexUtils.Mobile(mobile)) {
            Result res = new Result(ResultCode.COMMON_FAILED, false);
            return res;
        }
        // 解密，前端加密了。
        String mobileSecretKey = appBaseConfigService.getAppBaseConfig(ContextConstants.APP_ID,
                ContextConstants.CAPTCHA_SECRET_KEY);
        log.info("dengjie,app send mobile is:" + mobile);
        log.info("dengjie,mobileSecretKey is:" + mobileSecretKey);

        mobile = AESUtils.decrypt(mobile, mobileSecretKey);
        // 校验注册的时候手机号码是否已经注册过。如果没有注册过我们系统，那么就不能发验证码。保证该接口只针对已经有我们账号的用户使用。
        Result res = userService.mobileIsExisted(mobile);
        // false表示没有注册过
        if (res.isSuccess() == true) {
            // 生成验证码
            String captcha = captchaCacheDAO.getPasswordCaptcha(mobile);
            // 已经发送了验证码的，在缓存消失之前不能再生成。验证码设置了消失时间。即验证码有效期。
            // 获取有效期，当手机号在60s过后，是允许用户重新发送短信的，判定逻辑是获取key的TTL剩余有效时间来计算是否已经超过60s，而不是判断验证码缓存是否存储
            Long registerCaptchaTTL = captchaCacheDAO.getPasswordCaptchaTTL(mobile);
            Long expireTime = CaptchaCacheDAOImpl.CAPTCHA_EXPIRE_TIME;
            if (StringUtils.isBlank(captcha) || (expireTime - 60) > registerCaptchaTTL) {
                captcha = MathUtils.getRandowNumber(6);
                /** RPC调用消息系统发送短信，这里只做短信内容组装 **/
                Map<String, String> templateArgs = new HashMap<String, String>();
                templateArgs.put("code", captcha);
                templateArgs.put("product", "农商通APP");
                // 以后修改成springcloud内部接口调用
                SendSmsRequest sendSmsRequest = new SendSmsRequest();
                sendSmsRequest.setParamStrings(templateArgs);
                List<String> mobiles = new ArrayList<String>();
                mobiles.add(mobile);
                sendSmsRequest.setPhoneNumberArr(mobiles);
                sendSmsRequest.setTemplateCode("SMS_56085112");
                Map<String,String> headers = new HashMap<String,String>();
                headers.put("Accept", "application/vnd.dragon.app-v1.0+json");
                MyHttpclientUtils.doPostForJson(bizMainUrl.concat("/int/sms/send"), JSON.toJSONString(sendSmsRequest),
                        headers);
                // smsRPCService.sendToSingleUserDynaTemplate(mobile, SmsTemplate.RESET_PASSWORD_CAPTCHA, templateArgs);
                /** RPC调用消息系统发送短信，这里只做短信内容组装 **/
                res.setSuccess(true);
                if (res.isSuccess()) {
                    // 短信发送成功，把验证码设置到缓存中.
                    captchaCacheDAO.setPasswordCaptcha(mobile, captcha);
                    res.setResultCode(ResultCode.COMMON_SUCCESS);
                    res.setSuccess(true);
                }
            } else {
                res.setResultCode(ResultCode.COMMON_FAILED);
                res.setSuccess(false);
            }
        } else {
            // 并无该用户手机号，提示前端
            throw new BusinessException(ResultCode.SSO_FORGET_PASSWORD_MOBILE_NOT_EXISTED,
                    "the mobile is not exist,the mobile is：" + mobile);
        }
        return res;
    }

    @Override
    public Result validateRegisterCaptcha(String mobile, String captcha) {
        // 校验手机号码
        if (StringUtils.isBlank(mobile) || !RegexUtils.Mobile(mobile)) {
            throw new BusinessException(ResultCode.SSO_REGISTER_MOBILE_IS_ILLEGAL,
                    "register mobile is illegal,the mobile is：" + mobile);
        }
        // 校验验证码
        if (StringUtils.isBlank(captcha)) {
            throw new BusinessException(ResultCode.SSO_REGISTER_CAPTCHA_IS_ILLEGAL,
                    "register captcha is illegal,the captcha is：" + captcha);
        }
        // 这里需要调用redis来验证captcha是不是发给这个手机号的验证码
        String captchaCache = captchaCacheDAO.getRegisterCaptcha(mobile);
        if (!StringUtils.equals(captcha, captchaCache)) {
            // 如果相当那么校验通过
            log.error("register captcha is illegal,the captcha is：" + captcha);
            Result res = new Result(ResultCode.SSO_REGISTER_CAPTCHA_IS_ILLEGAL, false);
            return res;
        }
        Result res = new Result(ResultCode.COMMON_SUCCESS, true);
        return res;
    }

}
